#include "BlockQueue.hpp"
#include "RingQueue.hpp"
#include "Thread.hpp"
#include "Task.hpp"
#include <vector>
#include <string>
#include <ctime>

using namespace ThreadModule;
// using blockqueue_t = BlockQueue<Task>;
// using ringqueue_t = RingQueue<Task>;
using ringqueue_t = RingQueue<Task>;
// int a = 10;

void PrintHello()
{
  std::cout << "hello world" << std::endl;
}

void Consumer(ringqueue_t &rq, std::string name)
{
  while (true)
  {
    Task t;
    rq.Pop(&t);
    std::cout << "Consumer handler task :" << "[" << name << "]" << std::endl;
    t();
    // 从blockqueue_t取下来任务
    // Task t;
    // rq.Pop(&t); // 竞争和等待等逻辑在Pop中已经完成了
    // 处理任务
    // t(); // 所以这里是消费者私有
    // t.Excute();
    // std::cout << "Consumer Consum data is : " << t.ResultToString() << std::endl;
  }
}

void Productor(ringqueue_t &rq, std::string name)
{
  // srand(time(nullptr) ^ pthread_self());
  // int cnt = 10;
  while (true)
  {
    sleep(1);
    rq.Enqueue(Download);
    std::cout << "Productor product task" << "[" << name << "]" << std::endl;

    // 1. 获取任务
    // int a = rand() % 10 + 1;
    // usleep(1234);
    // int b = rand() % 20 + 1;
    // Task t(a, b);

    // 2.把获取的任务放入blockqueue_t队列
    // Task t = PrintHello;
    // rq.Enqueue(t);
    // std::cout << "Productor product data is : " << t.DebugToString() << std::endl;
  }
}

void InitCommon(std::vector<Thread<ringqueue_t>> *threads, int num, ringqueue_t &rq, func_t<ringqueue_t> func, const std::string &who)
{
  for (int i = 0; i < num; i++)
  {
    std::string name = "thread -" + std::to_string(i + 1) + "-" + who;
    threads->emplace_back(func, rq, name);
  }
}

void InitConsumer(std::vector<Thread<ringqueue_t>> *threads, int num, ringqueue_t &rq)
{
  InitCommon(threads, num, rq, Consumer, "consumer");
}

void InitProductor(std::vector<Thread<ringqueue_t>> *threads, int num, ringqueue_t &rq)
{
  InitCommon(threads, num, rq, Productor, "productor");
}

void StartAll(std::vector<Thread<ringqueue_t>> &threads)
{
  for (auto &thread : threads)
  {
    thread.Start();
  }
}

void WaitAllThread(std::vector<Thread<ringqueue_t>> &threads)
{
  for (auto &thread : threads)
  {
    thread.Join();
  }
}

int main()
{
  // blockqueue_t *bq = new blockqueue_t(5);
  ringqueue_t *rq = new ringqueue_t(10);
  std::vector<Thread<ringqueue_t>> threads;
  InitConsumer(&threads, 3, *rq);
  InitProductor(&threads, 2, *rq);

  StartAll(threads);
  WaitAllThread(threads);
}